package com.skivingcloud.develop.service.impl;

import com.mybatisflex.core.paginate.Page;
import com.mybatisflex.core.query.QueryMethods;
import com.mybatisflex.core.query.QueryWrapper;
import com.mybatisflex.spring.service.impl.ServiceImpl;
import com.skivingcloud.admin.utils.CommonConstant;
import com.skivingcloud.common.exceptions.BusinessException;
import com.skivingcloud.common.utils.PageParameter;
import com.skivingcloud.common.utils.UuidUtil;
import com.skivingcloud.develop.entity.SysBusinessDesigner;
import com.skivingcloud.develop.entity.SysBusinessDesignerComponent;
import com.skivingcloud.develop.entity.SysFormDesigner;
import com.skivingcloud.develop.mapper.SysBusinessDesignerMapper;
import com.skivingcloud.develop.mapper.SysFormDesignerMapper;
import com.skivingcloud.develop.service.SysBusinessDesignerComponentService;
import com.skivingcloud.develop.service.SysBusinessDesignerService;
import jakarta.annotation.Resource;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert;

import java.util.List;

/**
 * 应用设计记录 服务层实现。
 *
 * @author skivingcloud
 * @since 2024-01-18
 */
@Service
public class SysBusinessDesignerServiceImpl extends ServiceImpl<SysBusinessDesignerMapper, SysBusinessDesigner> implements SysBusinessDesignerService {
    private final SysFormDesignerMapper sysFormDesignerMapper;
    private final SysBusinessDesignerComponentService sysBusinessDesignerComponentService;

    public SysBusinessDesignerServiceImpl(SysFormDesignerMapper sysFormDesignerMapper, SysBusinessDesignerComponentService sysBusinessDesignerComponentService) {
        this.sysFormDesignerMapper = sysFormDesignerMapper;
        this.sysBusinessDesignerComponentService = sysBusinessDesignerComponentService;
    }

    /**
     * 分页查询应用设计记录
     *
     * @param parameter 查询参数
     * @return 分页查询结果
     */
    @Override
    public Page<SysBusinessDesigner> queryByPage(PageParameter<SysBusinessDesigner> parameter){
        Page<SysBusinessDesigner> page = new Page<>(parameter.getPage(), parameter.getPageSize());
        QueryWrapper queryWrapper = QueryWrapper.create().from(SysBusinessDesigner.class).as("oo")
                .join(
                        QueryWrapper.create().select(
                                        QueryMethods.column(SysBusinessDesigner::getDesignerCode),
                                        QueryMethods.max(QueryMethods.column(SysBusinessDesigner::getVersion)).as("version"))
                                .from(SysBusinessDesigner.class)
                                .groupBy(SysBusinessDesigner::getDesignerCode)).as("ii")
                .on(
                        wrapper -> wrapper.where("oo.designer_code = ii.designer_code")
                                .and("oo.version = ii.version")
                );
        SysBusinessDesigner sysBusinessDesigner = parameter.getParam();
        if(StringUtils.isNotBlank(sysBusinessDesigner.getDesignerCode())){
            queryWrapper.and(SysBusinessDesigner::getDesignerCode).like(sysBusinessDesigner.getDesignerCode());
        }
        if(StringUtils.isNotBlank(sysBusinessDesigner.getDesignerName())){
            queryWrapper.and(SysBusinessDesigner::getDesignerName).like(sysBusinessDesigner.getDesignerName());
        }
        if(StringUtils.isNotBlank(sysBusinessDesigner.getTypeCode())){
            queryWrapper.and(SysBusinessDesigner::getTypeCode).eq(sysBusinessDesigner.getTypeCode());
        }
        if(StringUtils.isNotBlank(sysBusinessDesigner.getHasTask())){
            queryWrapper.and(SysBusinessDesigner::getHasTask).eq(sysBusinessDesigner.getHasTask());
        }
        if(StringUtils.isNotBlank(sysBusinessDesigner.getTaskDefCode())){
            queryWrapper.and(SysBusinessDesigner::getTaskDefCode).like(sysBusinessDesigner.getTaskDefCode());
        }
        return this.page(page, queryWrapper);
    }
    
    /**
     * 根据编号获取表单信息
     *
     * @param designerCode 表单设计编号
     * @param type 类型：1-新增表单、2-修改表单、3-详情表单
     * @return 表单设计信息
     */
    @Override
    public SysBusinessDesigner getSysBusinessDesignerByCodeHasJson(String designerCode, String type) throws BusinessException{
        QueryWrapper queryWrapper = QueryWrapper.create().where(SysBusinessDesigner::getDesignerCode).eq(designerCode);
        SysBusinessDesigner sysBusinessDesigner = this.getOne(queryWrapper);
        if("1".equals(type)){
            SysFormDesigner sysFormDesigner = sysFormDesignerMapper.selectOneById(sysBusinessDesigner.getNewFormId());
            sysBusinessDesigner.setNewFormJson(sysFormDesigner.getFormDesJson());
        }else if("2".equals(type)){
            SysFormDesigner sysFormDesigner = sysFormDesignerMapper.selectOneById(sysBusinessDesigner.getModFormId());
            sysBusinessDesigner.setModFormJson(sysFormDesigner.getFormDesJson());
        }else if("3".equals(type)){
            SysFormDesigner sysFormDesigner = sysFormDesignerMapper.selectOneById(sysBusinessDesigner.getDetailFormId());
            sysBusinessDesigner.setDetailFormJson(sysFormDesigner.getFormDesJson());
        }else{
            throw new BusinessException("请传入正确的表单类型");
        }
        return sysBusinessDesigner;
    }

    /**
     * 根据id获取表单信息（包含表单下的组件信息）
     *
     * @param designerId 表单id
     * @return 表单信息
     */
    @Override
    public SysBusinessDesigner getSysBusinessDesignerHasDetail(String designerId) {
        SysBusinessDesigner designer = this.getById(designerId);
        Assert.notNull(designer, "查询的信息不存在");
        List<SysBusinessDesignerComponent> componentList = sysBusinessDesignerComponentService.queryByDesignerId(designerId);
        designer.setComponentList(componentList);
        return designer;
    }

    /**
     * 根据主键更新应用设计记录。若源记录已发布则生成新记录
     *
     * @param sysBusinessDesigner 应用设计记录
     * @return 结果
     */
    @Override
    public Boolean updateVersion(SysBusinessDesigner sysBusinessDesigner) {
        SysBusinessDesigner old = this.getById(sysBusinessDesigner.getId());
        if (CommonConstant.COMMON_YES_OR_NO_YES.equals(old.getResStatus())) {
            //如果源记录已发布则生成新纪录且版本+1
            sysBusinessDesigner.setId(UuidUtil.get32UUID());
            sysBusinessDesigner.setVersion(sysBusinessDesigner.getVersion() + 1);
            return this.save(sysBusinessDesigner);
        }else{
            return this.updateById(sysBusinessDesigner);
        }
    }

    /**
     * 根据编码获取最新版本已发布的信息
     *
     * @param code 表单设计编码
     * @return 表单设计详情
     */
    @Override
    public SysBusinessDesigner getLatestInfoByCode(String code) {
        QueryWrapper queryWrapper = QueryWrapper.create().from(SysBusinessDesigner.class).as("oo")
                .join(
                        QueryWrapper.create().select(
                                        QueryMethods.column(SysBusinessDesigner::getDesignerCode),
                                        QueryMethods.max(QueryMethods.column(SysBusinessDesigner::getVersion)).as("version"))
                                .from(SysBusinessDesigner.class)
                                .where(SysBusinessDesigner::getResStatus).eq(CommonConstant.COMMON_YES_OR_NO_YES)
                                .groupBy(SysBusinessDesigner::getDesignerCode)).as("ii")
                .on(
                        wrapper -> wrapper.where("oo.designer_code = ii.designer_code")
                                .and("oo.version = ii.version")
                ).where(SysBusinessDesigner::getDesignerCode).eq(code);
        SysBusinessDesigner designer = this.getOne(queryWrapper);
        Assert.notNull(designer, "查询的信息不存在");
        List<SysBusinessDesignerComponent> componentList = sysBusinessDesignerComponentService.queryByDesignerId(designer.getId());
        designer.setComponentList(componentList);
        return designer;
    }

    /**
     * 保存表单设计，如果状态为发布则同时根据表单、组件信息动态生成业务数据库表
     *
     * @param sysBusinessDesigner 表单设计信息
     * @return 结果
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean saveAndCreateTable(SysBusinessDesigner sysBusinessDesigner) {
        //保存表单设计
        boolean res = false;
        res = this.save(sysBusinessDesigner);
        sysBusinessDesigner.getComponentList().forEach(component -> {
            component.setId(UuidUtil.get32UUID());
            component.setDesignerId(sysBusinessDesigner.getId());
            component.setDesignerCode(sysBusinessDesigner.getDesignerCode());
            sysBusinessDesignerComponentService.save(component);
        });
        //根据表单信息动态生成数据库表
        if (CommonConstant.COMMON_YES_OR_NO_YES.equals(sysBusinessDesigner.getResStatus())) {
            createBusinessTale(sysBusinessDesigner);
        }
        return res;
    }

    /**
     * 根据表单、组件信息动态生成业务数据库表
     * @param sysBusinessDesigner 表单信息
     */
    private void createBusinessTale(SysBusinessDesigner sysBusinessDesigner) {
        //获取组件定义
    }
}
